/*
    This file is part of Starlight Engine.

    Starlight Engine is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 2 of the License, or
    (at your option) any later version.

    Starlight Engine is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Starlight Engine.  If not, see <http://www.gnu.org/licenses/>.
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;


namespace StarlightEngine
{
    /// <summary>
    /// Controls all functions within the engine.
    /// </summary>
    public static class Engine
    {
        static int frame = 0;
        static ContentManager content;
        static GraphicsDevice device;
        static SpriteBatch sBatch;
        static GameTime time;
        static ResourceContentManager resContent;
        static SpriteFont debFont;

        public static Matrix CameraMatrix
        {
            get { return SceneManager.ActiveScene.Camera.CameraMatrix; }
        }

        public static int Frames
        {
            get { return frame; }
        }

        /// <summary>
        /// Gets the debug font.
        /// </summary>
        /// <value>The debug font.</value>
        public static SpriteFont DebugFont
        {
            get { return debFont; }
        }

        /// <summary>
        /// Gets the resource content manager.
        /// </summary>
        /// <value>The resource content manager.</value>
        internal static ResourceContentManager ResourceContentManager
        {
            get { return resContent; }
        }


        /// <summary>
        /// Gets or sets the content manager.
        /// </summary>
        /// <value>The content manager.</value>
        public static ContentManager ContentManager
        {
            get { return content; }
            set { content = value; }
        }

        /// <summary>
        /// Gets or sets the graphics device.
        /// </summary>
        /// <value>The graphics device.</value>
        public static GraphicsDevice GraphicsDevice
        {
            get { return device; }
            set { device = value; }
        }

        /// <summary>
        /// Gets or sets the sprite batch.
        /// </summary>
        /// <value>The sprite batch.</value>
        public static SpriteBatch SpriteBatch
        {
            get { return sBatch; }
            set { sBatch = value; }
        }

        /// <summary>
        /// Gets the game time.
        /// </summary>
        /// <value>The game time.</value>
        public static GameTime GameTime
        {
            get { return time; }
        }

        /// <summary>
        /// Initializes the engine, with the specified game used for services.
        /// </summary>
        /// <param name="game">If from an XNA game, just use `this`.</param>
        public static void Initialize(Game game)
        {
            Logger.Write("Initializng Engine...", 2);
            //Use the game's intergral services, rather than overcompilcating and using our own.
            content = game.Content;
            device = game.GraphicsDevice;

            //Create a new spritebatch using the games GraphicsDevice.
            sBatch = new SpriteBatch(device);
            
            //Create a content manager for embedded content.
            resContent = new ResourceContentManager(game.Services, EngineResources.ResourceManager);

            //Texture manager initialization.
            TextureManager.Initialize();
            //SceneManager initialization.
            SceneManager.Initialize();
            //Input manager.
            InputManager.Initialize();

            //Load the debug font.
            //If on zune load the zune file, otherwise the windows file.
#if ZUNE
            debFont = resContent.Load<SpriteFont>("DebugFontZune");
#else
            debFont = resContent.Load<SpriteFont>("DebugFontWin");
#endif
            FontManager.Initialize();
            FontManager.AddFont("Engine.Font", debFont);
                
            Logger.Write("Finished Initializing Engine.", 2);
        }

        /// <summary>
        /// Ends this instance, disposing of resources.
        /// </summary>
        public static void End()
        {
            Logger.Write("Disposing of Engine", 2);
            content.Dispose();
            device.Dispose();
            sBatch.Dispose();
            Logger.Write("Done...", 2);
        }

        /// <summary>
        /// Draws the current scene and diagnostic information.
        /// </summary>
        /// <param name="time">The time.</param>
        public static void Draw(GameTime time)
        {
            Engine.time = time;
            Engine.device.Clear(Settings.ClearColor);
            //Uses camera matrix, for translation zoom and rotation.
            SpriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Texture, SaveStateMode.None, SceneManager.ActiveScene.Camera.CameraMatrix);
            SceneManager.ActiveScene.Draw();
            SpriteBatch.End();

            //Draw objects that should not move with camera.
            SpriteBatch.Begin();
            if (Settings.Debug)
            {
                //Draw the debug information, such as FPS, current touches, the locations of those touches and accelerometer values.
                DrawDebugInfo();
                InputManager.DrawDebug();
            }
            SpriteBatch.End();
            frame++;

        }

        /// <summary>
        /// Draws the debug info.
        /// </summary>
        static void DrawDebugInfo()
        {
            //We should be drawing FPS here, temporarily in InputManager to help with rotation.
            //SpriteBatch.DrawString(Engine.DebugFont, final.ToString(), Settings.DebugTextOffset, Settings.DebugTextColor);
        }

        /// <summary>
        /// Updates the engine.
        /// </summary>
        /// <param name="time">The time.</param>
        public static void Update(GameTime time)
        {
            //Update input.
            InputManager.Update();
            SceneManager.ActiveScene.Update();
        }
    }
}